home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 46 / Amiga Format CD46 (1999-10-20)(Future Publishing)(GB)[!][issue 1999-12].iso / -in_the_mag- / synth_studies / resgrep03b / source / export.cc next >
C/C++ Source or Header  |  1999-09-15  |  17KB  |  728 lines

  1. //
  2. // export.cc
  3. //
  4. //    This file contain the functions for exporting data from ResGrep.
  5. // Here are the bulidin-commands and the interface function to other, extern
  6. // commands addressed via ARexx.
  7. //
  8.  
  9. extern "C" {
  10. #include <exec/types.h>
  11. #include <intuition/intuition.h>
  12. #include <intuition/gadgetclass.h>
  13. #include <libraries/gadtools.h>
  14. #include <graphics/displayinfo.h>
  15. #include <dos/dos.h>
  16.  
  17. #include <stdlib.h>
  18. #include <math.h>
  19. char *strdup(char *);
  20. };
  21. #include "id.h"
  22. #include "export.h"
  23. #include "resgrep.h"
  24. #include "utils.h"
  25.  
  26. extern "C" {
  27. #include <clib/iffparse_protos.h>
  28. #include <clib/dos_protos.h>
  29. };
  30.  
  31.  
  32. #define ONE ((size_t)1)
  33.  
  34. exportfunc exportfunctions[4]=
  35. {
  36.    convert::rawdata,
  37.    convert::text2ascii,
  38.    convert::text2ftxt,
  39.    convert::snd28svx
  40. };
  41.  
  42. convert::convert(unsigned long theType,
  43.           int thefuncnum,
  44.           char *theName, char *theCommand, bool theIsARexx,
  45.           send theSendTo, char *theFilename,
  46.           bool thebuiltin)
  47.         : node(theName,nocopy,0,theType)
  48. {
  49.    funcnum = thefuncnum;
  50.    command = strdup(theCommand);
  51.    isARexx = theIsARexx;
  52.    sendto  = theSendTo;
  53.    filename= strdup(theFilename);
  54.    builtin = thebuiltin;
  55. }
  56.  
  57. convert::~convert(void)
  58. {
  59. }
  60.  
  61. list *conversions;
  62.  
  63. void initexport(void)
  64. {
  65.    conversions = new list();
  66.  
  67.    conversions->addtail(
  68.       new convert(ID_ICNd,4,"IFF-ILBM",
  69.           NULL,false,Clipboard,"T:IconOut"));
  70.    conversions->addtail(
  71.       new convert(ID_ICNd,0,"raw data",
  72.           NULL,false,File,"T:IconOut"));
  73.    conversions->addtail(
  74.       new convert(ID_STRd,2,"IFF-FTXT",
  75.           NULL,false,Clipboard));
  76.    conversions->addtail(
  77.       new convert(ID_STRd,0,"raw data",
  78.           NULL,false,File,"T:TextOut"));
  79.    conversions->addtail(
  80.       new convert(ID_STRd,1,"plain ASCII",
  81.           NULL,false,File,"T:TextOut"));
  82.    conversions->addtail(
  83.       new convert(ID_snd,3,"IFF-8SVX",
  84.           NULL,false,File,"T:SoundOut"));
  85.    conversions->addtail(
  86.       new convert(ID_snd,0,"raw data",
  87.           NULL,false,File,"T:SoundOut"));
  88.    conversions->addtail(
  89.       new convert(ID_icl4,5,"IFF-ILBM",
  90.           NULL,false,Clipboard,"T:IconOut"));
  91.    conversions->addtail(
  92.       new convert(ID_icl4,0,"raw data",
  93.           NULL,false,File,"T:IconOut"));
  94.    conversions->addtail(
  95.       new convert(ID_icl8,6,"IFF-ILBM",
  96.           NULL,false,Clipboard,"T:IconOut"));
  97.    conversions->addtail(
  98.       new convert(ID_icl8,0,"raw data",
  99.           NULL,false,File,"T:IconOut"));
  100.    conversions->addtail(
  101.       new convert(ID_icsd,7,"IFF-ILBM",
  102.           NULL,false,Clipboard,"T:IconOut"));
  103.    conversions->addtail(
  104.       new convert(ID_icsd,0,"raw data",
  105.           NULL,false,File,"T:IconOut"));
  106.    conversions->addtail(
  107.       new convert(ID_ics4,8,"IFF-ILBM",
  108.           NULL,false,Clipboard,"T:IconOut"));
  109.    conversions->addtail(
  110.       new convert(ID_ics4,0,"raw data",
  111.           NULL,false,File,"T:IconOut"));
  112.    conversions->addtail(
  113.       new convert(ID_ics8,9,"IFF-ILBM",
  114.           NULL,false,Clipboard,"T:IconOut"));
  115.    conversions->addtail(
  116.       new convert(ID_ics8,0,"raw data",
  117.           NULL,false,File,"T:IconOut"));
  118.  
  119. }
  120.  
  121. int convert::getfuncnum(void)
  122. {
  123.    return funcnum;
  124. }
  125.  
  126. int exportres(unsigned long theType, FILE *fp, unsigned long DataOffset)
  127. {
  128.    node  *n;
  129.    convert *c;
  130.    int     ret;
  131.  
  132.    if( (n=conversions->findpack(theType)) == NULL )
  133.       return ERR_NO_CONVERS;
  134.    c=(convert *)n;
  135.    switch( c->getfuncnum() )
  136.    {
  137.     case 0:
  138.       ret=c->rawdata(fp,DataOffset);
  139.       break;
  140.     case 1:
  141.       ret=c->text2ascii(fp,DataOffset);
  142.       break;
  143.     case 2:
  144.       ret=c->text2ftxt(fp,DataOffset);
  145.       break;
  146.     case 3:
  147.       ret=c->snd28svx(fp,DataOffset);
  148.       break;
  149.     case 4:
  150.       ret=c->ICNd2ilbm(fp,DataOffset);
  151.       break;
  152.     case 5:
  153.       ret=c->icl42ilbm(fp,DataOffset);
  154.       break;
  155.     case 6:
  156.       ret=c->icl82ilbm(fp,DataOffset);
  157.       break;
  158.     case 7:
  159.       ret=c->icsd2ilbm(fp,DataOffset);
  160.       break;
  161.     case 8:
  162.       ret=c->ics42ilbm(fp,DataOffset);
  163.       break;
  164.     case 9:
  165.       ret=c->ics82ilbm(fp,DataOffset);
  166.       break;
  167.     default:
  168.       ResError("Fatal:\nUnknown function detected\nduring data export.");
  169.       break;
  170.    }
  171.    c->docommand();
  172.    return ret;
  173. }
  174.  
  175. void convert::docommand(void)
  176. {
  177.    if( isARexx )
  178.    {
  179.       ResWarning("Sorry!\nARexx Port not implemented yet.\n");
  180.       return;
  181.    }
  182.    system(command);
  183. }
  184.  
  185. //------------------------------------ all  ---
  186.  
  187. char          *buffer=NULL;
  188. unsigned long  bufferlen;
  189.  
  190. int readdata(FILE *fp, unsigned long offset)
  191. {
  192.    if( buffer!=NULL )
  193.       free(buffer);
  194.    buffer=NULL;
  195.    bufferlen=0;
  196.    rewind(fp);
  197.    if( fseek(fp,offset,SEEK_SET)!=0 )
  198.       return ERR_FILE_CORRUPTED;
  199.    if( fread((void *)&bufferlen,sizeof(unsigned long),ONE,fp)!=ONE )
  200.       return ERR_FILE_CORRUPTED;
  201.    if( (buffer=(char *)malloc(bufferlen))==NULL )
  202.       return ERR_NO_MEMORY;
  203.    if( fread((void *)buffer,sizeof(char),bufferlen,fp)!=bufferlen )
  204.    {
  205.       free(buffer);
  206.       buffer=NULL;
  207.       return ERR_FILE_CORRUPTED;
  208.    }
  209.    return ERR_NO;
  210. }
  211.  
  212. //------------------------------------ RawData
  213. int convert::rawdata(FILE *fp, unsigned long DataOffset)
  214. {
  215.    int             ret;
  216.    FILE          *out;
  217.  
  218.    if( sendto!=File )
  219.    {
  220.       ResError("It's stricly forbidden to\nwrite non-iff files\n"
  221.            "to the clipboard");
  222.       return 1;
  223.    }
  224.  
  225.    if( (ret=readdata(fp,DataOffset))!=ERR_NO )
  226.       return ret;
  227.  
  228.    if( (out=fopen(filename,"w"))==NULL )
  229.       return ERR_FILE_OPEN;
  230.  
  231.    fwrite(buffer,sizeof(char),bufferlen,out);
  232.  
  233.    fclose(out);
  234.    return ERR_NO;
  235. }
  236.  
  237.  
  238.  
  239. //------------------------------------ STR#
  240.  
  241. int convert::text2ascii(FILE *fp, unsigned long DataOffset)
  242. {
  243.    int             ret;
  244.    unsigned short   *StrNum;
  245.    unsigned char    *StrLen;
  246.    char         *buf;
  247.    int             index;
  248.  
  249.    if( (ret=readdata(fp,DataOffset))!=ERR_NO )
  250.       return ret;
  251.  
  252.    if( sendto==File )
  253.    {
  254.       FILE *out;
  255.  
  256.       if( (out=fopen(filename,"w"))==NULL )
  257.      return ERR_FILE_OPEN;
  258.       StrNum = (unsigned short *)buffer;
  259.       buf=buffer+sizeof(unsigned short);
  260.  
  261.       // Einmal über alle Strings
  262.       for(index=0;
  263.       index < (int)(*StrNum);
  264.      index++)
  265.       {
  266.      StrLen = (unsigned char *)buf++;
  267.      if( fwrite(buf,sizeof(unsigned char),(size_t)(*StrLen),out)
  268.          != (size_t)(*StrLen) )
  269.      {
  270.         fclose(out);
  271.         return ERR_WRITE;
  272.      }
  273.      buf+= *StrLen;
  274.      fprintf(out,"\n");
  275.       }
  276.       fclose(out);
  277.    }
  278.    return ERR_NO;
  279. }
  280.  
  281. int convert::text2ftxt(FILE *fp, unsigned long DataOffset)
  282. {
  283.    int             ret;
  284.    unsigned short   *StrNum;
  285.    unsigned char    *StrLen;
  286.    char         *buf;
  287.    struct IFFHandle *iff;
  288.    char          newline='\n';
  289.  
  290.    if( (ret=readdata(fp,DataOffset))!=ERR_NO )
  291.       return ret;
  292.  
  293.    if( (iff=AllocIFF())==NULL )
  294.       return ERR_NO_MEMORY;
  295.  
  296.    if( sendto==Clipboard )
  297.    {
  298.       if( (iff->iff_Stream=(ULONG)OpenClipboard(0))==NULL )
  299.       {
  300.      FreeIFF(iff);
  301.      return ERR_NO_CLIPBOARD;
  302.       }
  303.       InitIFFasClip(iff);
  304.    }
  305.    else if( sendto=File )
  306.    {
  307.       if( (iff->iff_Stream=(ULONG)Open((UBYTE *)filename,MODE_NEWFILE))==NULL )
  308.       {
  309.      FreeIFF(iff);
  310.      return ERR_NO_FILE;
  311.       }
  312.       InitIFFasDOS(iff);
  313.    }
  314.  
  315.    if( OpenIFF(iff,IFFF_WRITE)!=0 )
  316.    {
  317.       ResError("Error occured during 'OpenIFF()'.");
  318.       return ERR_OPENIFF;
  319.    }
  320.  
  321.    if( (ret=PushChunk(iff,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))!=0 )
  322.    {
  323.       ResError("Error while writing the\n'FORM' chunk.");
  324.       return ERR_WRITE;
  325.    }
  326.    if( (ret=PushChunk(iff,ID_FTXT,ID_CHRS,IFFSIZE_UNKNOWN))!=0 )
  327.    {
  328.       ResError("Error while writing the\n'FTXT' chunk.");
  329.       return ERR_WRITE;
  330.    }
  331.  
  332.    StrNum = (unsigned short *)buffer;
  333.    buf=buffer+sizeof(unsigned short);
  334.  
  335.    // Einmal über alle Strings
  336.    for(int index=0; index <(int)(*StrNum); index++)
  337.    {
  338.       StrLen = (unsigned char *)buf++;
  339.       if( WriteChunkBytes(iff,(UBYTE *)buf,(LONG)*StrLen)!=(LONG)*StrLen )
  340.      return ERR_WRITE;
  341.       buf+= *StrLen;
  342.       WriteChunkBytes(iff,&newline,1);
  343.    }
  344.  
  345.    if( PopChunk(iff)!=0 )  // pop the CHRS
  346.    {
  347.       ResError("Error while poping the\n'CHRS' chunk.");
  348.       return 1;
  349.    }
  350.  
  351.    if( PopChunk(iff)!=0 )  // pop the FORM
  352.    {
  353.       ResError("Error while poping the\n'FORM' chunk.");
  354.       return 1;
  355.    }
  356.  
  357.    CloseIFF(iff);
  358.  
  359.    if( sendto==Clipboard )
  360.       CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
  361.    else if( sendto==File )
  362.    {
  363.       Close((BPTR)iff->iff_Stream);
  364.    }
  365.  
  366.    FreeIFF(iff);
  367.    return ERR_NO;
  368. }
  369.  
  370. // ---------------------------------------------- snd
  371. // This is only a minimal version. It greps the first
  372. // digitizes sound.
  373. int convert::snd28svx(FILE *fp, unsigned long DataOffset)
  374. {
  375.    int             ret, index;
  376.    unsigned short          *SndType;
  377.    unsigned short          *NumberOfCommands, *cmd;
  378.    char          *buf;
  379.    char          *BegOfSound;
  380.    struct IFFHandle *iff;
  381.  
  382.    struct VoiceHeader    // Ami
  383.    {
  384.       unsigned long    NumSamples;
  385.       unsigned long    NumRepeatSamples;
  386.       unsigned long    NumRepeats;
  387.       unsigned short    SampleRate;
  388.       unsigned char    NumOct;
  389.       unsigned char    Compression;
  390.       unsigned long    Volume;
  391.    } vh;
  392.  
  393.    struct SoundHeader    // Mac
  394.    {
  395.       unsigned long    samplePrt;
  396.       unsigned long    length;
  397.       unsigned long    sampleRate;
  398.       unsigned long    loopStart;
  399.       unsigned long    loopEnd;
  400.       unsigned short    priv;
  401.       char        sampleArea[1];
  402.    } *sh;
  403.  
  404.  //      unsigned long     encode;
  405.  //      unsigned long     baseFrequency;
  406.  
  407.    if( (ret=readdata(fp,DataOffset))!=ERR_NO )
  408.       return ret;
  409.  
  410.    buf=buffer;
  411.  
  412.    // Dann erst einmal die Daten suchen (vielleicht gibt es ja gar nichts
  413.    // digitalisiertes.)
  414.  
  415.  
  416.  
  417.    SndType=(unsigned short *)buf;
  418.    buf+=sizeof(short);
  419.    if( *SndType!=0x0001 )
  420.    {
  421.       ResError("Mac snd type is not '0x0001'.");
  422.       return ERR_NO_MEMORY;   // ???
  423.    }
  424.  
  425.    // Skip Modifiers
  426.    NumberOfCommands=(unsigned short *)buf;
  427.    buf+=sizeof(short);
  428.    // Skip them
  429.    buf+=6* *NumberOfCommands;
  430.  
  431.    // Parse Commands
  432.    NumberOfCommands=(unsigned short *)buf;
  433.    buf+=sizeof(short);
  434.  
  435.    for(index=0; index< *NumberOfCommands; index++)
  436.    {
  437.       cmd=(unsigned short *)buf;
  438.       if( (*cmd & 0x7FFF) == 81 )
  439.      break;
  440.       buf+=8;
  441.    }
  442.    if( (*cmd & 0x7FFF) != 81 )
  443.       return ERR_NO_MEMORY;
  444.  
  445.    sh=(struct SoundHeader *) (  buffer + *( (unsigned long *)(buf+4) )  );
  446.    BegOfSound = &(sh->sampleArea[0]);
  447.  
  448.    for(index=0; index<sh->length; index++)
  449.       *(BegOfSound+index) ^= 0x80;
  450.  
  451.    if( (iff=AllocIFF())==NULL )
  452.       return ERR_NO_MEMORY;
  453.  
  454.    if( sendto==Clipboard )
  455.    {
  456.       if( (iff->iff_Stream=(ULONG)OpenClipboard(0))==NULL )
  457.       {
  458.      FreeIFF(iff);
  459.      return ERR_NO_CLIPBOARD;
  460.       }
  461.       InitIFFasClip(iff);
  462.    }
  463.    else if( sendto=File )
  464.    {
  465.       if( (iff->iff_Stream=(ULONG)Open((UBYTE *)filename,MODE_NEWFILE))==NULL )
  466.       {
  467.      FreeIFF(iff);
  468.      return ERR_NO_FILE;
  469.       }
  470.       InitIFFasDOS(iff);
  471.    }
  472.  
  473.    if( OpenIFF(iff,IFFF_WRITE)!=0 )
  474.    {
  475.       ResError("Error occured during 'OpenIFF()'.");
  476.       return ERR_OPENIFF;
  477.    }
  478.  
  479.    if( (ret=PushChunk(iff,ID_8SVX,ID_FORM,IFFSIZE_UNKNOWN))!=0 )
  480.    {
  481.       ResError("Error while writing the\n'FORM' chunk.");
  482.       return ERR_WRITE;
  483.    }
  484.    if( (ret=PushChunk(iff,ID_8SVX,ID_VHDR,sizeof(struct VoiceHeader)))!=0 )
  485.    {
  486.       ResError("Error while writing the\n'VHDR' chunk.");
  487.       return ERR_WRITE;
  488.    }
  489.  
  490.    // Schreiben des VHDR
  491.    vh.NumSamples       = sh->length;
  492.    vh.NumRepeatSamples = 0;
  493.    vh.NumRepeats       = 0;
  494.    vh.SampleRate       = (short) (sh->sampleRate / 65536);
  495.    vh.NumOct           = 1;
  496.    vh.Compression      = 0;
  497.    vh.Volume           = (unsigned long) (64 * 65536);
  498.  
  499.    if( WriteChunkBytes(iff,(UBYTE *)&vh,sizeof(struct VoiceHeader))
  500.       !=sizeof(struct VoiceHeader) )
  501.       return ERR_WRITE;
  502.  
  503.    if( PopChunk(iff)!=0 )  // pop the VHDR
  504.    {
  505.       ResError("Error while poping the\n'VHDR' chunk.");
  506.       return 1;
  507.    }
  508.  
  509.    if( (ret=PushChunk(iff,ID_8SVX,ID_BODY,sh->length))!=0 )
  510.    {
  511.       printf("BODY: Fehler beim schreiben der Daten (%4d).\n",ret);
  512.       return ERR_WRITE;
  513.    }
  514.  
  515.    if( WriteChunkBytes(iff,(UBYTE *)BegOfSound,sh->length)!=sh->length )
  516.       return ERR_WRITE;
  517.  
  518.    if( PopChunk(iff)!=0 )  // pop the BODY
  519.    {
  520.       ResError("Error while poping\n'BODY' chunk.");
  521.       return 1;
  522.    }
  523.  
  524.    if( PopChunk(iff)!=0 )  // pop the FORM
  525.    {
  526.       ResError("Error while poping\n'FORM' chunk.");
  527.       return 1;
  528.    }
  529.  
  530.    CloseIFF(iff);
  531.  
  532.    if( sendto==Clipboard )
  533.       CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
  534.    else if( sendto==File )
  535.    {
  536.       Close((BPTR)iff->iff_Stream);
  537.    }
  538.  
  539.    FreeIFF(iff);
  540.    return ERR_NO;
  541.  
  542. }
  543.  
  544. // ------------------------------------------------------ ICONS
  545. int convert::ICNd2ilbm(FILE *fp, unsigned long DataOffset)
  546. {
  547.    return icons2ilbm(fp,DataOffset,32,32,1);
  548. }
  549.  
  550. int convert::icl42ilbm(FILE *fp, unsigned long DataOffset)
  551. {
  552.    return icons2ilbm(fp,DataOffset,32,32,4);
  553. }
  554.  
  555. int convert::icl82ilbm(FILE *fp, unsigned long DataOffset)
  556. {
  557.    return icons2ilbm(fp,DataOffset,32,32,8);
  558. }
  559.  
  560. int convert::icsd2ilbm(FILE *fp, unsigned long DataOffset)
  561. {
  562.    return icons2ilbm(fp,DataOffset,16,16,1);
  563. }
  564.  
  565. int convert::ics42ilbm(FILE *fp, unsigned long DataOffset)
  566. {
  567.    return icons2ilbm(fp,DataOffset,16,16,4);
  568. }
  569.  
  570. int convert::ics82ilbm(FILE *fp, unsigned long DataOffset)
  571. {
  572.    return icons2ilbm(fp,DataOffset,16,16,8);
  573. }
  574.  
  575. int convert::icons2ilbm(FILE *fp, unsigned long DataOffset,
  576.             unsigned long x, unsigned long y,
  577.             unsigned long ftiefe)
  578. {
  579.    unsigned char **planes;
  580.    int index, pixel, offset, zeile;
  581.    int ret;
  582.    struct IFFHandle *iff;
  583.  
  584.    // Amiga BitMapHeader
  585.    struct BitMapHeader
  586.    {
  587.       unsigned short width;
  588.       unsigned short height;
  589.       short         xpos;
  590.       short         ypos;
  591.       unsigned char  numplanes;
  592.       unsigned char  mask;
  593.       unsigned char  compression;
  594.       unsigned char  privat;
  595.       unsigned short transp;
  596.       unsigned char  xsize;
  597.       unsigned char  ysize;
  598.       short         ux;
  599.       short         uy;
  600.    } bmh;
  601.  
  602.    if( x%8!=0 )  // X muss ein Vielfaches von 8 sein
  603.       return 1;
  604.  
  605.    if( (ret=readdata(fp,DataOffset))!=ERR_NO )
  606.       return ret;
  607.  
  608.    if( (planes=(unsigned char **)malloc(ftiefe*sizeof(unsigned char *)))
  609.       ==NULL)
  610.       return 2;
  611.    for(index=0; index<ftiefe; index++)
  612.       if( (planes[index]=(unsigned char *)
  613.          calloc(x*y/8,sizeof(unsigned char)))==NULL )
  614.      return 3;
  615.  
  616.    // Für jede Bitplane
  617.    for(offset=0; offset<ftiefe; offset++)
  618.       for(pixel=offset, index=0; pixel<x*y*ftiefe; pixel+=ftiefe, index++)
  619.      if( GETBIT(buffer,pixel)==1 )
  620.         SETBIT(planes[offset],index);
  621.  
  622.    if( (iff=AllocIFF())==NULL )
  623.       return ERR_NO_MEMORY;
  624.  
  625.    if( sendto==Clipboard )
  626.    {
  627.       if( (iff->iff_Stream=(ULONG)OpenClipboard(0))==NULL )
  628.       {
  629.      FreeIFF(iff);
  630.      return ERR_NO_CLIPBOARD;
  631.       }
  632.       InitIFFasClip(iff);
  633.    }
  634.    else if( sendto=File )
  635.    {
  636.       if( (iff->iff_Stream=(ULONG)Open((UBYTE *)filename,MODE_NEWFILE))==NULL )
  637.       {
  638.      FreeIFF(iff);
  639.      return ERR_NO_FILE;
  640.       }
  641.       InitIFFasDOS(iff);
  642.    }
  643.  
  644.    if( OpenIFF(iff,IFFF_WRITE)!=0 )
  645.    {
  646.       ResError("Error occured during 'OpenIFF()'.");
  647.       return ERR_OPENIFF;
  648.    }
  649.  
  650.    if( (ret=PushChunk(iff,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN))!=0 )
  651.    {
  652.       ResError("Error while writing the\n'FORM' chunk.");
  653.       return ERR_WRITE;
  654.    }
  655.    if( (ret=PushChunk(iff,ID_ILBM,ID_BMHD,sizeof(struct BitMapHeader)))!=0 )
  656.    {
  657.       ResError("Error while writing the\n'BMHD' chunk.");
  658.       return ERR_WRITE;
  659.    }
  660.  
  661.    // Schreiben des BMH
  662.    bmh.width         = x;
  663.    bmh.height         = y;
  664.    bmh.xpos         = 0;
  665.    bmh.ypos         = 0;
  666.    bmh.numplanes     = ftiefe;
  667.    bmh.mask         = 0;
  668.    bmh.compression   = 0;
  669.    bmh.privat         = 0;
  670.    bmh.transp         = 0;
  671.    bmh.xsize         = 1;
  672.    bmh.ysize         = 1;
  673.    bmh.ux         = x;
  674.    bmh.uy         = y;
  675.  
  676.    if( WriteChunkBytes(iff,(UBYTE *)&bmh,sizeof(struct BitMapHeader))
  677.       !=sizeof(struct BitMapHeader) )
  678.       return ERR_WRITE;
  679.  
  680.    if( PopChunk(iff)!=0 )  // pop the BMHD
  681.    {
  682.       ResError("Error while poping the\n'BMHD' chunk.");
  683.       return 1;
  684.    }
  685.  
  686.    if( (ret=PushChunk(iff,ID_ILBM,ID_BODY,x*y/8*ftiefe))!=0 )
  687.    {
  688.       printf("BODY: Fehler beim schreiben der Daten (%4d).\n",ret);
  689.       return ERR_WRITE;
  690.    }
  691.  
  692. //printf("Schreibe ILBM-BODY\n");
  693.    // Schreiben des ILBM
  694.    for(zeile=0; zeile<y; zeile++)
  695.       for(index=0; index<ftiefe; index++)
  696.      if( WriteChunkBytes(iff,(UBYTE *)planes[index]+x/8*zeile,x/8)!=x/8 )
  697.         return ERR_WRITE;
  698. //printf("Fertig mit schreiben des ILBM-BODY\n");
  699.  
  700.    if( PopChunk(iff)!=0 )  // pop the BODY
  701.    {
  702.       ResError("Error while poping\n'BODY' chunk.");
  703.       return 1;
  704.    }
  705.    if( PopChunk(iff)!=0 )  // pop the FORM
  706.    {
  707.       ResError("Error while poping\n'FORM' chunk.");
  708.       return 1;
  709.    }
  710.  
  711.    CloseIFF(iff);
  712.  
  713.    if( sendto==Clipboard )
  714.       CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
  715.    else if( sendto==File )
  716.    {
  717.       Close((BPTR)iff->iff_Stream);
  718.    }
  719.  
  720.    FreeIFF(iff);
  721.    for(index=0; index<ftiefe; index++)
  722.       free(planes[index]);
  723.    free(planes);
  724.    return ERR_NO;
  725. }
  726.  
  727.  
  728.